﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Forest.Core;
using Forest.Cat.Domain.Shared;
using Forest.Core.Data;

namespace Forest.Cat.Domain.Services
{
    public class GenerateNumberService : IGenerateNumberService
    {
        public Guid CreateId(Guid currentId, GenerateType type = GenerateType.Resume)
        {
            // 获取默认采番号
            var defaultId = ConstManager.DefaultIds[type];

            // 获取最小数字
            var minId = Convert.ToDouble(defaultId.ToString().Split('-').LastOrDefault());

            // 如果为默认值，则数据库没有数据
            if (currentId != Guid.Empty)
            {
                // 判断是否有不规则号存在
                bool isErrorId = false;
                int index = 0;
                var currentIdList = currentId.ToString().Split('-').Select(s =>
                    {
                        double number = 0;
                        if (index > 0)
                        {
                            if (!double.TryParse(s, out number))
                            {
                                isErrorId = true;
                            }
                        }
                        index++;
                        return number;
                    }).ToList();

                // 返回默认ID号
                if (isErrorId)
                {
                    return defaultId;
                }

                // 最大的ID数字
                double maxPartId = 0;

                // 最大的Id数字存在的部分
                int maxPartNumber = 0;

                // 循环获取最大部分的号以及最大的数字
                for (int i = 1; i < 5; i++)
                {
                    var partId = currentIdList[i];
                    if (i == 4)
                    {
                        if (partId >= minId)
                        {
                            maxPartId = partId + 1;
                            maxPartNumber = i;
                            if (maxPartNumber > ConstManager.PartMaxs[i])
                            {
                                maxPartId = 1;
                                maxPartNumber = i - 1;
                            }
                        }
                        else
                        {
                            return defaultId;
                        }
                    }
                    else
                    {
                        if (partId > 0)
                        {
                            maxPartId = partId + 1;
                            maxPartNumber = i;
                            if (maxPartNumber > ConstManager.PartMaxs[i])
                            {
                                maxPartId = 1;
                                maxPartNumber = i - 1;
                            }
                            break;
                        }
                    }
                }
                if (maxPartNumber < 1)
                {
                    throw new OverflowException("采番号溢出！");
                }
                if (maxPartId == 0)
                {
                    return defaultId;
                }

                // 拼接ID
                IList<string> numberList = new List<string>();
                numberList.Add(defaultId.ToString().Split('-').FirstOrDefault());
                for (int i = 1; i < maxPartNumber; i++)
                {
                    numberList.Add("0".PadLeft(ConstManager.PartNumbers[i], '0'));
                }
                numberList.Add((maxPartId.ToString().Split('.').FirstOrDefault() ?? "0").PadLeft(ConstManager.PartNumbers[maxPartNumber], '0'));
                for (int i = maxPartNumber + 1; i < 5; i++)
                {
                    numberList.Add("9".PadLeft(ConstManager.PartNumbers[i], '9'));
                }

                // 返回ID
                return new Guid(string.Join("-", numberList));
            }
            else
            {
                return defaultId;
            }
        }

        public Guid GenerateId<T>(IRepository<T> repository, GenerateType type = GenerateType.Resume) where T : BaseEntity
        {
            var maxId = repository.Table.Select(s => s.Id).OrderByDescending(s => s).FirstOrDefault();
            var currentId = this.CreateId(maxId, type);
            while (true)
            {
                var item = repository.GetById(currentId);
                if (item == null)
                {
                    break;
                }
                currentId = this.CreateId(currentId, type);
            }
            return currentId;
        }
    }
}
